#pragma once
#include <iostream>
#include "Epoller.hpp"
#include <memory>
#include "Connection.hpp"
#include <unordered_map>
using namespace EpollerModule;

using connection_t = std::shared_ptr<Connection>;
// 负责管理connect
class Reactor
{
    const static int event_num = 1024;

public:
    Reactor() : _isrunning(false), _epoller(std::make_unique<Epoller>())
    {
        _epoller->Init();
    }
    void DisPatch(int n)
    {
        for (int i = 0; i < n; i++)
        {
            int fd = _revs[i].data.fd;
            uint32_t events = _revs[i].events;
            if ((events & EPOLLIN) || (events & EPOLLERR))
            {
                events = EPOLLIN | EPOLLOUT; // 将异常转化为读写，使得发生的错误都出现在读写时，方便写异常处理
            }
            if (events & EPOLLIN && IsConnectionExist(fd))
            {
                _connections[fd]->Recever();
            }
            if (events & EPOLLOUT && IsConnectionExist(fd))
            {
                _connections[fd]->Sender();
            }
        }
    }
    void Stop()
    {
        _isrunning = false;
    }
    bool IsConnectionExist(int fd)
    {
        return _connections.find(fd) != _connections.end();
    }
    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(_revs, event_num, timeout);
        DisPatch(n);
    }
    void Loop()
    {
        _isrunning = true;
        int timeout = -1;
        while (_isrunning)
        {
            LoopOnce(timeout);
        }
        _isrunning = false;
    }
    void EnableReadWrite(int sockfd,bool readable,bool writeable)
    {
        if(IsConnectionExist(sockfd))
        {
            uint32_t events = (readable? EPOLLIN : 0) | (writeable? EPOLLOUT : 0)| EPOLLET;
            _connections[sockfd]->SetEvents(events);
            _epoller->Update(sockfd, _connections[sockfd]->Events());
        }

    }
    void InsertConnection(connection_t con)
    {
        auto iter = _connections.find(con->Fd());
        if (iter == _connections.end())
        {
            _connections.insert(std::make_pair(con->Fd(), con));
            // 把链接写到epoll

            _epoller->Add(con->Fd(), con->Events());
            con->SetOwner(this);
        }
    }
    void DeleteConnection(int sockfd)
    {
        if(IsConnectionExist(sockfd))
        {
            //移除内核对fd的关心
            _epoller->Delete(sockfd);
            _connections[sockfd]->Close();
            //在对connection的管理中移除
            _connections.erase(sockfd);
        }
    }
    ~Reactor() {}

private:
    int _port;
    std::unique_ptr<Epoller> _epoller;
    std::unordered_map<int, connection_t> _connections; // 当前服务器内部所有链接
    bool _isrunning;
    struct epoll_event _revs[event_num];
};